<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <script>
        // 简易es5实现promise

        // promise 基础实例
        // var p = new Promise(function (resolve, reject) {
        //     console.log('begin to execute!');
        //     const num = 1;
        //     if (num === 0) {
        //         resolve('Success!');
        //     } else {
        //         reject('Failure');
        //     }
        // });
        // p.then(function (data) {
        //     console.log('resolve: ', data);
        // }).catch(err => {
        //     console.log('reject', err)
        // });

        // promise es5实现
        // 在这里只是实现简单的promise api，我们的目标主要集中在以下几个，因为是最常用的。
        // 1. Promise.prototype.resolve
        // 2. Promise.prototype.reject
        // 3. Promise.prototype.then
        // 4. Promise.all
        // 5. Promise.race

        // 实现resolve，reject和then
        // function Promise(resolver) {
        //     if (typeof resolver !== 'function') {
        //         throw new TypeError('Promise resolver ' + resolver + ' is not a function')
        //     }
        //     this.resolver = resolver;
        //     this.success = null;
        //     this.error = null;
        //     this.status = null;
        // }
        // Promise.prototype.resolve = function (value) {
        //     if (typeof this.success == 'function') {
        //         this.status = true;
        //         console.log(11111111111111)
        //         this.success(value);
        //     }
        // }
        // Promise.prototype.reject = function (value) {
        //     if (typeof this.error == 'function') {
        //         this.status = false;
        //         console.log(1111111111111122222222222222)
        //         this.error(value);
        //     }
        // }
        // Promise.prototype.then = function (onFulfilled, onRejected) {
        //     this.success = onFulfilled;
        //     this.error = onRejected;
        //     var self = this;
        //     console.log(this.status)
        //     self.resolver(self.resolve.bind(self), self.reject.bind(self));
        //     return new Promise(function (resolve, reject) {
        //         console.log('sssssssss', self.status)
        //         if (self.status === true && onFulfilled) {
        //             return resolve(onFulfilled())
        //         }
        //         if (self.status === false && onRejected) {
        //             return reject(onRejected())
        //         }
        //     });
        // }
        // Promise.prototype.catch = function (onRejected) {
        //     return this.then(null, onRejected)
        // }
        /**
         * Promise类实现原理
         * 构造函数传入一个function，有两个参数，resolve：成功回调; reject：失败回调
         * status: 状态存储 [PENDING-进行中 RESOLVED-成功 REJECTED-失败]
         * doneList: 成功处理函数列表
         * failList: 失败处理函数列表
         * done: 注册成功处理函数
         * fail: 注册失败处理函数
         * then: 同时注册成功和失败处理函数
         * always: 一个处理函数注册到成功和失败
         * resolve: 更新state为：RESOLVED，并且执行成功处理队列
         * reject: 更新state为：REJECTED，并且执行失败处理队列
        **/

        const status = {
            PENDING: 'pending',
            RESOLVED: 'resolved',
            REJECTED: 'rejected'
        }

        class PromiseNew {
            constructor(resolver) {
                this.status = status.PENDING;
                this.value = null;
                this.resolvedQueue = []
                this.rejectedQueue = []
                resolver(this.resolve.bind(this), this.reject.bind(this));
            }
            addQueue(self, resolve, reject) {
                typeof resolve === 'function' && self.resolvedQueue.push(resolve);
                typeof reject === 'function' && self.rejectedQueue.push(reject);
            }
            // 同时注册成功和失败处理函数
            then(success, fail) {
                if (this.status === status.PENDING) {
                    this.addQueue(this, success, fail);
                }
                else if (typeof success === 'function' && this.status === status.RESOLVED) {
                    success(this.value);
                } else if (typeof fail === 'function' && this.status === status.REJECTED) {
                    fail(this.value);
                }
                return this;
            }
            resolve(value) {
                this.status = status.RESOLVED;
                this.value = value;
                console.log(this)
                this.resolvedQueue.forEach((item) => {
                    this.value = item(this.value);
                })
            }
            // Promise规范当中，规定Promise只能从初始pending状态变到resolved或者rejected状态，是单向变化的
            reject(value) {
                this.status = status.REJECTED;
                this.value = value;
                this.rejectedQueue.forEach((item) => {
                    this.value = item(this.value);
                })
            }
            catch(fn) {
                if (typeof fn === 'function') {
                    if (this.status === status.PENDING) {
                        this.addQueue(this, null, fn);
                    }
                    else if (this.status === status.REJECTED) {
                        fn(this.value);
                    }
                }
                return this;
            }
        }

        PromiseNew.resolve = (value) => {
            return new PromiseNew((resolve, reject) => {
                resolve(value);
            })
        }

        PromiseNew.reject = (value) => {
            return new PromiseNew((resolve, reject) => {
                reject(value);
            })
        }

        PromiseNew.all = promiseArr => {
            return new PromiseNew(function (resolve, reject) {
                let proNum = promiseArr.length;
                let count = 0;
                let messageMap = [];
                // 统一根据状态进行判断
                function handle(promise) {
                    // 判断是否已经改变
                    if (promise.status == status.RESOLVED) {
                        messageMap.push(promise.value); // 不论先后，先存入map中
                        count++;
                        // 所有都resolved才能够，达到总体的resolved
                        if (count == proNum) {
                            resolve(messageMap)
                        }
                    } else {
                        // 只要出现一个reject，则全部都rejected掉
                        reject(new Error(promise));
                    }
                }
                promiseArr.forEach((promise, index) => {
                    if (!(promise instanceof PromiseNew)) throw Error('必须传入PromiseNew对象');
                    return promise.then(res => {
                        handle(promise, index)
                    }).catch(err => {
                        handle(promise, index)
                    });
                });
            })
        }

        PromiseNew.resolve('测试终端').then(res => {
            console.log(res)
        }).catch((res) => {
            console.log(res);
        })

        // new PromiseNew((resolve, reject) => {
        //     setTimeout(() => {
        //         resolve('hello world');
        //     })
        // }).then((res) => {
        //     // PromiseNew.all([
        //     //     new PromiseNew((resolve, reject) => {
        //     //         setTimeout(() => {
        //     //             resolve('异步函数');
        //     //         })
        //     //     }),
        //     //     new PromiseNew((resolve, reject) => {
        //     //         setTimeout(() => {
        //     //             resolve('异步函数1');
        //     //         })
        //     //     }),
        //     //     new PromiseNew((resolve, reject) => {
        //     //         setTimeout(() => {
        //     //             resolve('异步函数2');
        //     //         })
        //     //     })],
        //     // ).then(res => {
        //     //     console.log(res, 1000090)
        //     // });
        // }).then((res) => {
        //     // console.log(res.then((res) => {
        //     console.log(res, 4477);
        //     // }), 11111);
        // }).catch((res) => {
        //     console.log(res, 'failure');
        // }).catch((res) => {
        //     console.log(res, 'failure');
        // })

        // console.log(
        //     new Promise(function (re) {
        //         re('aa')
        //     }).then
        // )

        // Promise.all([Promise.resolve(true).then(() => {
        //     return false;
        // })]).then((res) => {
        //     console.log(res)
        // })

        // let myPromise1 = new Promise(function (resolve, reject) {
        //     console.log('begin to execute!');
        //     const num = 0;
        //     if (num === 0) {
        //         resolve('Success!');
        //     } else {
        //         reject('Failure');
        //     }
        // });
        // Promise.all([myPromise, myPromise1]).then((successMessage) => {
        //     console.log(successMessage);
        // }).catch(err => {
        //     console.log('错误!', err)
        // });
    </script>
</body>

</html>